
/*
 * @Author: qsy
 * @Date: 2024-07-22 16:08:55
 * @LastEditors: qsy
 * @LastEditTime: 2025-04-06 13:43:03
 * @Description: 连接wifi
 */

#include "wifi_connect.h"

#define EXAMPLE_ESP_MAXIMUM_RETRY  3 // 最大重试次数
bool ret = false; // wifi连接结果

/* FreeRTOS event group to signal when we are connected*/
EventGroupHandle_t s_wifi_event_group;

EventGroupHandle_t my_wifi_connected_event_group;

/* The event group allows multiple bits for each event, but we only care about two events:
 * - we are connected to the AP with an IP
 * - we failed to connect after the maximum amount of retries */


static const char *TAG = "wifi station";

static int s_retry_num = 0;

/**
 * @description: wifi回调处理函数
 * @return {*}
 */
static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        // esp_wifi_connect(); 在外面已经连接了，这里不需要再次连接
    }
    // wifi断开 
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
        // ESP_LOGI(TAG, "WiFi disconnected, reason: %d", event->reason);
        
        switch (event->reason) {
                // 超时 当密码错误来处理
                case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
                    // ESP_LOGI(TAG, "Not authenticated (wrong password)");
                    xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
                    break;
                // 没找到账号
                case WIFI_REASON_NO_AP_FOUND:
                    xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
                    break;
                
                // 默认失败
                default:
                    xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
                    break;
        }
        // 这部分不要重连！！！！！
    }
    // wifi连接成功 
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {

        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        // ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);

        mqtt_app_start();

    }
}

/**
 * @description: 初始化wifi模块、以及NVS存储
 * @return {*}
 */
void wifi_model_NVS_init(void) {

    // #ifndef WIFI_INIT_SELECT
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_ERROR_CHECK(esp_netif_init()); // 初始化网络接口
    // 初始化事件循环
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    // 创建默认的WiFi STA接口
    esp_netif_create_default_wifi_sta();
    // #else
    // // 如果开启了OTA，则不初始化wifi模块
    // #endif

    // 初始化WiFi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    // 设置WiFi存储模式为RAM
    // ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    // 设置WiFi模式为STA模式
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));

    // 启动WiFi
    ESP_ERROR_CHECK(esp_wifi_start());
    // 设置wifi信道
    ESP_ERROR_CHECK( esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE));
}



/**
 * @description: wifi连接
 * @param {uint8_t} scan_result_ap_count
 * @param {char} *password
 * @param {char} *ssid
 * @return {*}
 */
bool wifi_connect(uint8_t scan_result_ap_count, char *password, char *ssid)
{
    s_wifi_event_group = xEventGroupCreate();
    my_wifi_connected_event_group = xEventGroupCreate();

    // 选择一个AP进行连接
    if (scan_result_ap_count > 0) {
        wifi_config_t wifi_config = {
            .sta = {
                .ssid = {0},
                .password = {0},
                .threshold.authmode = 0,
                .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
            },
        };
        strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid) - 1);
        strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password) - 1); // 假设密码为"password"


        esp_event_handler_instance_t instance_any_id; // 注册事件处理函数
        esp_event_handler_instance_t instance_got_ip;
        ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                            ESP_EVENT_ANY_ID,
                                                            &event_handler,
                                                            NULL,
                                                            &instance_any_id));
        ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                            IP_EVENT_STA_GOT_IP,
                                                            &event_handler,
                                                            NULL,
                                                            &instance_got_ip));

        ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
        ESP_ERROR_CHECK(esp_wifi_connect()); // 连接到AP
        ESP_LOGI(TAG, "wifi_init_sta finished.");

        // 等待WiFi连接成功或失败,这个等待是必须的
        EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
                                               WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
                                               pdFALSE,
                                               pdFALSE,
                                               portMAX_DELAY);

        if (bits & WIFI_CONNECTED_BIT) {
            ret = true;
            // 成功之后对mqtt操作，mqtt连接成功之后再发送成功事件
        } else if (bits & WIFI_FAIL_BIT) {
            ret = false;
            ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));// 注销事件处理函数
            ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id)); // 注销事件处理函数
        } else {
            ret = false;
            ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));// 注销事件处理函数
            ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id)); // 注销事件处理函数
        }

        ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));// 注销事件处理函数
        ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id)); // 注销事件处理函数
        vEventGroupDelete(s_wifi_event_group);
        return ret;
    } else {
        ESP_LOGE(TAG, "No AP found to connect");
        ret = false;
        return ret;
    }
}
